package timing.ukulele.gateway.handler;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import timing.ukulele.gateway.client.PortalClient;
import timing.ukulele.gateway.config.JwtProperties;
import timing.ukulele.gateway.entity.AuthUserDetails;
import timing.ukulele.gateway.utils.JWTUtil;
import timing.ukulele.common.Constant;
import timing.ukulele.common.ResponseResult;
import timing.ukulele.common.ResultCode;
import timing.ukulele.common.portal.UserData;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.server.WebFilterExchange;
import org.springframework.security.web.server.authentication.WebFilterChainServerAuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;


@Component
public class AuthenticationSuccessHandler extends WebFilterChainServerAuthenticationSuccessHandler {

    private PortalClient portalClient;
    private final JwtProperties jwtProperties;

    public AuthenticationSuccessHandler(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }

    @Lazy
    @Resource
    public void setPortalClient(PortalClient portalClient) {
        this.portalClient = portalClient;
    }

    @Override
    public Mono<Void> onAuthenticationSuccess(WebFilterExchange webFilterExchange, Authentication authentication) {
        ServerWebExchange exchange = webFilterExchange.getExchange();
        ServerHttpResponse response = exchange.getResponse();
        //设置headers
        HttpHeaders httpHeaders = response.getHeaders();
        httpHeaders.add("Content-Type", "application/json; charset=UTF-8");
        httpHeaders.add("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
        //设置body
        ResponseResult<AuthUserDetails> result = ResponseResult.success();
        byte[] dataBytes = {};
        ObjectMapper mapper = new ObjectMapper();
        try {
            User user = (User) authentication.getPrincipal();
            AuthUserDetails userDetails = buildUser(user);
            Map<String, Object> map = new HashMap<>(2);
            map.put(Constant.USER_INFO, userDetails);
            final String token4JwtAuth = JWTUtil.createJavaWebToken4JwtAuth(map, jwtProperties.getSecretKey(), jwtProperties.getValidityInMs());
            httpHeaders.add(Constant.TOKEN, token4JwtAuth);
            userDetails.setToken(token4JwtAuth);
            result.setData(userDetails);
            dataBytes = mapper.writeValueAsBytes(result);
        } catch (Exception ex) {
            ex.printStackTrace();
            Map<String, Object> map = new HashMap<>(4);
            map.put("status", ResultCode.UNAUTHORIZED.getCode());
            map.put("message", "授权异常");
            dataBytes = JSON.toJSONString(map).getBytes();
        }
        DataBuffer bodyDataBuffer = response.bufferFactory().wrap(dataBytes);
        return response.writeWith(Mono.just(bodyDataBuffer));
    }


    private AuthUserDetails buildUser(User user) {
        AuthUserDetails userDetails = new AuthUserDetails();
        final ResponseResult<UserData> result = portalClient.findByUsername(user.getUsername());
        if (result != null && result.getData() != null) {
            UserData data = result.getData();
            userDetails.setUsername(user.getUsername());
            userDetails.setSystemIds(data.getSystemIds());
            userDetails.setRole(data.getRoleId());
        }
        return userDetails;
    }
}
